package services

import (
	"context"
	"github.com/golang/protobuf/ptypes/empty"
	"github.com/golang/protobuf/ptypes/wrappers"

	context2 "kop/framework/context"
	"kop/framework/errors"
	"kop/modules/award/models"
	"kop/modules/item/consts"
	"kop/pb"

	itemC "kop/modules/item/client"
	maidC "kop/modules/maid/client"
	moneyC "kop/modules/money/client"
	questC "kop/modules/quest/client"
	roleC "kop/modules/role/client"
)

type MaidService struct {
	context2.Context
}

func (s *MaidService) ClassUp(ctx context.Context, req *pb.APIMaidClassUpRequest) (*pb.APIMaidReply, error) {

	return maidC.MaidService.ClassUp(ctx, req)
}

func (s *MaidService) SkillUp(ctx context.Context, req *pb.APIMaidSkillUpRequest) (*pb.APIMaidReply, error) {

	return maidC.MaidService.SkillUp(ctx, req)
}

// 约会选择地点
func (s *MaidService) DateStep1(ctx context.Context, req *pb.DateStep1Request) (*pb.APIMaidDateReply, error) {

	return maidC.MaidService.DateStep1(ctx, req)
}

// 约会问答环节
func (s *MaidService) DateStep2(ctx context.Context, req *pb.DateStep2Request) (*pb.APIMaidDateReply, error) {

	return maidC.MaidService.DateStep2(ctx, req)
}

// 送礼
func (s *MaidService) Present(ctx context.Context, req *pb.APIMaidPresentRequest) (*pb.APIMaidPresentReply, error) {

	var reply pb.APIMaidPresentReply

	var roleID = s.GetRoleID(ctx)

	maid, err := maidC.GetMaid(roleID, req.MaidID)
	if err != nil {
		return &reply, err
	}

	// 固定一个道具
	if reply.Item, err = itemC.DelItem(roleID, s.GetServerID(ctx), req.ItemID, 1); err != nil {
		return &reply, err
	}

	res, err := maidC.MaidService.Present(ctx, req)
	if err != nil {
		return &reply, err
	}

	reply.Intimacy = res.Intimacy - maid.Intimacy
	reply.Charm = res.Charm - maid.Charm
	reply.Maid = res
	return &reply, nil
}

func (s *MaidService) BarDate(ctx context.Context, req *empty.Empty) (*pb.MaidDateResp, error) {

	var roleID = s.GetRoleID(ctx)
	var maidDate = maidC.GetMaidDate(roleID)
	if maidDate.BarDateNum == 0 {
		return &pb.MaidDateResp{}, errors.ParamError
	}

	maidDate.BarDateNum -= 1
	maidC.SaveDate(maidDate)

	var reply, err = maidC.MaidService.BarDate(ctx, req)
	if err == nil {
		reply.MaidDate = maidDate

		// quest
		go questC.Date(roleID, s.GetServerID(ctx), 1, reply.Intimacy)
	}

	return reply, err
}

const (
	BarNormalAwardID = 30001 // 未招募船长奖励
	BarLuckAwardID   = 30002 // 已招募船长奖励
)

// 酒吧喝一杯
func (s *MaidService) BarDrink(ctx context.Context, req *empty.Empty) (*pb.BarDrinkReply, error) {

	var reply pb.BarDrinkReply
	var roleID = s.GetRoleID(ctx)

	var res, err = maidC.MaidService.Drink(ctx, req)
	if err != nil {
		return &reply, err
	}

	if res.Maid == nil {

		reply.CaptainEvent = &pb.CaptainEvent{
			CaptainID: res.CaptainID,
			Luck:      res.Luck,
		}

		var role = roleC.GetRole(roleID)
		if res.Luck {
			reply.CaptainEvent.Award = models.RandAward(role, BarLuckAwardID)
		} else {
			reply.CaptainEvent.Award = models.RandAward(role, BarNormalAwardID)
		}

		if err = models.SendAward(role, reply.CaptainEvent.Award); err != nil {
			return &reply, err
		}

	}

	go questC.DailyQuestBar(roleID, 1)

	reply.Maid = res.Maid
	reply.MaidDate = res.MaidDate
	return &reply, nil
}

// 银币许愿
func (s *MaidService) BarWishCoin(ctx context.Context, _ *empty.Empty) (*pb.BarWishCoinReply, error) {

	var reply pb.BarWishCoinReply
	var roleID = s.GetRoleID(ctx)

	var maidDate = maidC.GetMaidDate(roleID)
	if maidDate.BarLuck.Luck > 90 {
		return &reply, errors.New("银币最高到90")
	}

	var err error
	reply.Money, err = moneyC.SubCoin(ctx, maidDate.BarLuck.NeedCoin)
	if err != nil {
		return &reply, err
	}

	maidDate.BarLuck.WishNum += 1
	maidDate.BarLuck.Luck += 2
	maidC.SaveDate(maidDate)

	reply.MaidDate = maidDate
	return &reply, nil
}

const WishDiamond = 50

// 金币或钻石许愿
func (s *MaidService) BarWishItem(ctx context.Context, req *wrappers.Int32Value) (*pb.BarWishItemReply, error) {

	var reply pb.BarWishItemReply
	var roleID = s.GetRoleID(ctx)

	if req.Value != consts.Diamond && req.Value != consts.Gold {
		return &reply, errors.ParamError
	}

	var item pb.RawItem

	var maidDate = maidC.GetMaidDate(roleID)
	switch req.Value {
	case consts.Gold:
		if maidDate.BarLuck.Luck > 90 {
			return &reply, errors.ParamError
		}
		item = *maidDate.BarLuck.RawItem

		maidDate.BarLuck.Luck += 2

	case consts.Diamond:
		if maidDate.BarLuck.Luck > 100 {
			return &reply, errors.ParamError
		}
		item.ItemID = req.Value
		item.Number = WishDiamond

		maidDate.BarLuck.Luck += 10
	}

	var err error
	if reply.Item, err = itemC.DelItem(roleID, s.GetServerID(ctx), item.ItemID, item.Number); err != nil {
		return &reply, err
	}

	maidDate.BarLuck.WishNum += 1
	maidC.SaveDate(maidDate)

	reply.MaidDate = maidDate
	return &reply, nil
}

// 一键请酒
func (s *MaidService) OneKeyDrink(ctx context.Context, req *empty.Empty) (*pb.OneKeyDrinkReply, error) {

	var reply pb.OneKeyDrinkReply
	var roleID = s.GetRoleID(ctx)

	var maidDate = maidC.GetMaidDate(roleID)
	if maidDate.BarDrinkNum == 0 {
		return &reply, errors.ParamError
	}

	var items = make(map[int32]int32)
	var role = roleC.GetRole(roleID)

	for i := 0; i < int(maidDate.BarDrinkNum); i++ {
		var res, err = maidC.MaidService.Drink(ctx, req)
		if err != nil {
			return &reply, err
		}

		reply.MaidDate = res.MaidDate

		if res.Maid == nil {
			if res.Luck {
				var award = models.RandAward(role, BarLuckAwardID)
				for _, v := range award.AwardItems {
					items[v.RawItem.ItemID] = items[v.RawItem.ItemID] + v.RawItem.Number
				}
			} else {
				var award = models.RandAward(role, BarNormalAwardID)
				for _, v := range award.AwardItems {
					items[v.RawItem.ItemID] = items[v.RawItem.ItemID] + v.RawItem.Number
				}
			}
		} else {
			if reply.Maids == nil {
				reply.Maids = []*pb.Maid{}
			}
			reply.Maids = append(reply.Maids, res.Maid)
		}
	}

	if len(items) > 0 {
		//reply.Award = &pb.Award{ append(award.AwardItems, &pb.AwardItem{RawItem: &pb.RawItem{ItemID: itemID, Number: number}})
		reply.Award = &pb.Award{AwardItems: make([]*pb.AwardItem, 0, len(items))}
		for itemID, number := range items {
			reply.Award.AddRawItem(&pb.RawItem{ItemID: itemID, Number: number})
		}

		if err := models.SendAward(role, reply.Award); err != nil {
			return &reply, err
		}
	}

	//questC.Bar(roleID, maidDate.BarDrinkNum)
	// 日常任务
	questC.DailyQuestBar(roleID, maidDate.BarDrinkNum)

	return &reply, nil
}

// 一键约会
func (s *MaidService) OneKeyBarDate(ctx context.Context, req *empty.Empty) (*pb.OneKeyBarDateReply, error) {

	var reply = pb.OneKeyBarDateReply{Res: make([]*pb.MaidDateResp, 0)}
	var roleID = s.GetRoleID(ctx)

	reply.MaidDate = maidC.GetMaidDate(roleID)
	if reply.MaidDate.BarDateNum == 0 {
		return &reply, errors.ParamError
	}

	var n = int(reply.MaidDate.BarDateNum)

	reply.MaidDate.BarDateNum = 0
	maidC.SaveDate(reply.MaidDate)

	var intimacy int32
	for i := 0; i < n; i++ {

		var res, err = maidC.MaidService.BarDate(ctx, req)
		if err != nil {
			return &reply, err
		}

		intimacy += res.Intimacy
		reply.Res = append(reply.Res, res)
	}

	// quest
	go questC.Date(roleID, s.GetServerID(ctx), int64(n), intimacy)
	return &reply, nil
}

func (*MaidService) RestoreDrink(ctx context.Context, req *empty.Empty) (*pb.MaidDate, error) {

	return maidC.MaidService.RestoreDrink(ctx, req)
}

func (*MaidService) RestoreDate(ctx context.Context, req *empty.Empty) (*pb.MaidDate, error) {

	return maidC.MaidService.RestoreDate(ctx, req)
}

func (*MaidService) Garden(ctx context.Context, req *empty.Empty) (*pb.GardenResp, error) {

	return maidC.MaidService.Garden(ctx, req)
}

func (*MaidService) Kid(ctx context.Context, req *wrappers.Int32Value) (*pb.KidResp, error) {

	return maidC.MaidService.Kid(ctx, req)
}

func (*MaidService) GetRansom(ctx context.Context, req *wrappers.Int32Value) (*pb.GetRansomResp, error) {

	return maidC.MaidService.GetRansom(ctx, req)
}

func (*MaidService) PayRansom(ctx context.Context, req *wrappers.Int32Value) (*empty.Empty, error) {

	return maidC.MaidService.PayRansom(ctx, req)
}

func (*MaidService) UpGarden(ctx context.Context, req *empty.Empty) (*wrappers.Int32Value, error) {

	return maidC.MaidService.UpGarden(ctx, req)
}

func (*MaidService) OneKeyKid(ctx context.Context, req *wrappers.Int32Value) (*pb.KidResp, error) {

	return maidC.MaidService.OneKeyKid(ctx, req)
}
